package com.uu.platform.exception;

import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.uu.platform.result.ArgumentInvalidResult;
import com.uu.platform.result.ResultFactory;
import net.sf.json.JSONException;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.*;

@ControllerAdvice
//如果返回的为json数据或其它对象，添加该注解
@ResponseBody
public class GlobalExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    //添加全局异常处理流程，根据需要设置需要处理的异常，本文以MethodArgumentNotValidException为例
    @ExceptionHandler(value= MethodArgumentNotValidException.class)
    public Object MethodArgumentNotValidHandler(HttpServletRequest request,
                                                MethodArgumentNotValidException exception) throws Exception
    {
        //按需重新封装需要返回的错误信息
        List<ArgumentInvalidResult> invalidArguments = new ArrayList<>();
        //解析原错误信息，封装后返回，此处返回非法的字段名称，原始值，错误信息
        for (FieldError error : exception.getBindingResult().getFieldErrors()) {
            ArgumentInvalidResult invalidArgument = new ArgumentInvalidResult();
            invalidArgument.setDefaultMessage(error.getDefaultMessage());
            invalidArgument.setField(error.getField());
            invalidArgument.setRejectedValue(error.getRejectedValue());
            invalidArguments.add(invalidArgument);
        }
        return ResultFactory.buildFailResult("对象异常", invalidArguments);
    }
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Object hadeConstraintViolationException(ConstraintViolationException exception) {
        HashMap<String, Object> errors = new HashMap<>();
        Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
        String message = exception.getMessage();
        System.err.println("message = " + message);
        violations.forEach(c -> {
            String val = c.getMessage();
            String key = c.getPropertyPath().toString();
            errors.put(key, val);
        });
        return ResultFactory.buildFailResult("参数异常", errors);
    }
    @ExceptionHandler(value = AuthorizationException.class)
    public Object handleException(AuthorizationException e) {
        //e.printStackTrace();
        logger.info("权限异常");
        Map<String, String> result = new HashMap<String, String>();
        result.put("status", "400");
        //获取错误中中括号的内容
        String message = e.getMessage();
        String msg=message.substring(message.indexOf("[")+1,message.indexOf("]"));
        //判断是角色错误还是权限错误
        if (message.contains("role")) {
            result.put("msg", "对不起，您没有" + msg + "角色");
        } else if (message.contains("permission")) {
            result.put("msg", "对不起，您没有" + msg + "权限");
        } else {
            result.put("msg", "对不起，您的权限有误");
        }
        return result;
    }
    @ExceptionHandler(value = JSONException.class)
    public Object JSONExceptionHandler(JSONException e) {
        return ResultFactory.buildFailResult("JSONException(90%为转化异常)", e.getMessage());
    }
    /**
     * 拦截业务异常，返回业务异常信息
     * @param exception
     * @return
     */
    @ExceptionHandler(value = CmdcException.class)
    //@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public Object CmdcExceptionHandler(CmdcException exception) {
        int code = exception.getCode();
        String message = exception.getMessage();
        return ResultFactory.buildResult(code,message, null);
        //return new JsonResult(code, message);
    }
    /**
     * SQL SERVER 异常信息
     * @param exception
     * @return
     */
    @ExceptionHandler(value = SQLServerException.class)
    public Object SQLServerExceptionHandler(SQLServerException exception) {
        String message = exception.getMessage();
        return ResultFactory.buildResult(400,"SQLServerException", message);
    }

    /**
     * SQL SERVER 异常信息 SQL希望返回一行数据，但实际select得到的，超过一行数据
     * @param exception
     * @return
     */
    @ExceptionHandler(value = TooManyResultsException.class)
    public Object TooManyResultsExceptionHandler(TooManyResultsException exception) {
        String message = exception.getMessage();
        return ResultFactory.buildResult(400,"TooManyResultsException", message);
    }
}